package model

import (
	"context"
	"database/sql"
	"fmt"

	"github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
)

var _ SysRoleModel = (*customSysRoleModel)(nil)

type (
	// SysRoleModel is an interface to be customized, add more methods here,
	// and implement the added methods in customSysRoleModel.
	SysRoleModel interface {
		sysRoleModel
		withSession(session sqlx.Session) SysRoleModel
		Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
		TransInsert(ctx context.Context, session sqlx.Session, data *SysRole) (sql.Result, error)
		TransUpdate(ctx context.Context, session sqlx.Session, data *SysRole) error
		TransDelete(ctx context.Context, session sqlx.Session, id int64) error
		Page(ctx context.Context, page uint64, limit uint64, roleName string) (uint32, []*SysRole, error)
		Find(ctx context.Context, roleName string) ([]*SysRole, error)
	}

	customSysRoleModel struct {
		*defaultSysRoleModel
	}
)

// NewSysRoleModel returns a model for the database table.
func NewSysRoleModel(conn sqlx.SqlConn) SysRoleModel {
	return &customSysRoleModel{
		defaultSysRoleModel: newSysRoleModel(conn),
	}
}

func (m *customSysRoleModel) withSession(session sqlx.Session) SysRoleModel {
	return NewSysRoleModel(sqlx.NewSqlConnFromSession(session))
}

func (m *customSysRoleModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {

	return m.conn.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
		return fn(ctx, session)
	})

}

func (m *customSysRoleModel) TransInsert(ctx context.Context, session sqlx.Session, data *SysRole) (sql.Result, error) {
	query := fmt.Sprintf("insert into %s (%s) values (?, ?)", m.table, sysRoleRowsExpectAutoSet)
	ret, err := session.ExecCtx(ctx, query, data.RoleName, data.Remark)
	return ret, err
}

func (m *customSysRoleModel) TransDelete(ctx context.Context, session sqlx.Session, id int64) error {
	query := fmt.Sprintf("delete from %s where `role_id` = ?", m.table)
	_, err := session.ExecCtx(ctx, query, id)
	return err
}

func (m *customSysRoleModel) Page(ctx context.Context, page uint64, limit uint64, roleName string) (uint32, []*SysRole, error) {

	statementBuilder := squirrel.StatementBuilder

	if len(roleName) > 0 {
		statementBuilder = statementBuilder.Where(squirrel.Like{"role_name": "%" + roleName + "%"})
	}

	//查询列表
	pageSqlBuilder := statementBuilder.Select(sysUserRows).From(m.table).Limit(limit).Offset((page - 1) * limit).OrderBy("id desc")

	query, args, err := pageSqlBuilder.ToSql()
	if err != nil {
		return 0, nil, err
	}
	var resp []*SysRole
	err = m.conn.QueryRowsCtx(ctx, &resp, query, args...)
	if err != nil {
		return 0, nil, err
	}

	//查询总数
	countSqlBuilder := statementBuilder.Select("count(id)").From(m.table)
	if err != nil {
		return 0, nil, err
	}
	queryCount, args, err := countSqlBuilder.ToSql()
	var count uint32

	if err := m.conn.QueryRowCtx(ctx, &count, queryCount, args); err != nil {
		return 0, nil, err
	}

	return count, resp, nil

}

func (m *customSysRoleModel) Find(ctx context.Context, roleName string) ([]*SysRole, error) {

	statementBuilder := squirrel.StatementBuilder

	if len(roleName) > 0 {
		statementBuilder = statementBuilder.Where(squirrel.Like{"role_name": "%" + roleName + "%"})
	}

	//查询列表
	sqlBuilder := statementBuilder.Select(sysUserRows).From(m.table).OrderBy("id desc")

	query, args, err := sqlBuilder.ToSql()
	if err != nil {
		return nil, err
	}
	var resp []*SysRole
	err = m.conn.QueryRowsCtx(ctx, &resp, query, args...)
	if err != nil {
		return nil, err
	}

	return resp, nil
}

func (m *customSysRoleModel) TransUpdate(ctx context.Context, session sqlx.Session, data *SysRole) error {
	query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, sysRoleRowsWithPlaceHolder)
	_, err := m.conn.ExecCtx(ctx, query, data.RoleName, data.Remark, data.Id)
	return err
}
